package com.liyong.pullorder.sdk.client;

import com.liyong.pullorder.sdk.autoconfigure.PullOrderSdkProperties;
import lombok.extern.slf4j.Slf4j;
import org.apache.http.client.config.RequestConfig;
import org.apache.http.impl.client.CloseableHttpClient;
import org.apache.http.impl.client.DefaultHttpRequestRetryHandler;
import org.apache.http.impl.client.HttpClients;
import org.apache.http.impl.conn.PoolingHttpClientConnectionManager;
import org.springframework.http.client.HttpComponentsClientHttpRequestFactory;
import org.springframework.http.converter.StringHttpMessageConverter;
import org.springframework.web.client.RestTemplate;

import java.nio.charset.StandardCharsets;

/**
 * @author 葡萄味的萝卜
 * @date 2025/10/21 10:53
 *
 * HTTP客户端连接池配置管理
 *
 * 核心作用：基于Apache HttpClient提供高性能连接池，应对高并发拉单场景
 * 解决痛点：初期各平台对接方式分散，网络稳定性差异导致的连接超时问题
 *
 * 核心功能：
 * - 连接池管理,支持200个并发连接,避免频繁创建连接
 * - 连接复用，避免频繁TCP握手,提高性能
 * - 动态超时配置，适配不同平台网络环境,防止请求阻塞
 */
@Slf4j
public class HttpClientConfig {
    private final PullOrderSdkProperties properties;

    public HttpClientConfig(PullOrderSdkProperties properties) {
        this.properties = properties;
        log.info("初始化HTTP客户端配置，连接池大小: {}", properties.getHttpClient().getMaxTotal());
    }

    /**
     * 创建RestTemplate实例
     * 作用：包装HTTP客户端，提供便捷的REST API调用方式
     * 封装连接池能力，提供简洁的REST API调用接口
     * 应用场景：调用各平台订单API接口
     */
    public RestTemplate restTemplate() {
        RestTemplate restTemplate = new RestTemplate(clientHttpRequestFactory());
        // 添加响应编码处理，应对各平台返回格式差异
        restTemplate.getMessageConverters().add(0, new StringHttpMessageConverter(StandardCharsets.UTF_8));
        return restTemplate;
    }

    /**
     * 创建HTTP请求工厂
     * 作用：底层使用Apache HttpClient，支持连接池和高级网络特性
     */
    HttpComponentsClientHttpRequestFactory clientHttpRequestFactory() {
        HttpComponentsClientHttpRequestFactory factory = new HttpComponentsClientHttpRequestFactory();
        factory.setHttpClient(httpClient());
        // 设置连接池获取连接的超时时间
        factory.setConnectionRequestTimeout(properties.getHttpClient().getConnectionRequestTimeout());
        return factory;
    }

    /**
     * 创建连接池化的HTTP客户端
     * 关键技术：
     * 1. 连接池管理：避免频繁创建销毁连接
     * 2. 超时控制：动态适配不同平台网络环境
     * 3. 连接复用：提升性能，降低资源消耗
     */
    private CloseableHttpClient httpClient() {
        // 请求级别配置：连接超时、读取超时等
        RequestConfig requestConfig = RequestConfig.custom()
                .setConnectTimeout(properties.getHttpClient().getConnectTimeout())
                .setSocketTimeout(properties.getHttpClient().getSocketTimeout())
                .setConnectionRequestTimeout(properties.getHttpClient().getConnectionRequestTimeout())
                .build();

        // 连接池配置：支撑日均10万+订单拉取
        PoolingHttpClientConnectionManager connectionManager = new PoolingHttpClientConnectionManager();
        connectionManager.setMaxTotal(properties.getHttpClient().getMaxTotal());
        connectionManager.setDefaultMaxPerRoute(properties.getHttpClient().getMaxPerRoute());

        // 构建高性能HTTP客户端
        return HttpClients.custom()
                .setConnectionManager(connectionManager)
                .setDefaultRequestConfig(requestConfig)
                // 启用重试机制，应对网络抖动
                .setRetryHandler(new DefaultHttpRequestRetryHandler(2, true))
                .build();
    }

}
